import datetime
import json
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.utils import timezone
from django.core.files import File

from common.utils import str_to_dt
from course.models import (
    Course, Lecture,
)
from exam.models import (
    Exam, Problem, ExamPaper, Answer, InlineComment,
)
from user.contants import (
    GROUP_SUPERVISOR, SITE_GROUPS
)
from user.models import (
    User, EnrollmentHistory,
    StudyExperience, WorkExperience,
)
from resume.models import (
    Resume, ResumeComment
)
from task.models import Task
from interview.models import Interview


class Command(BaseCommand):
    help = 'insert test data into db'

    def teach_course(self, teacher, course):
        teacher.teaching.add(course)

    def enroll_course(self, student, course):
        student.enrolling.add(course)
        enrollment = EnrollmentHistory.objects.create(
            user=student, course=course,
            date=timezone.now(),
        )
        return enrollment

    def _read_courses(self):
        with open('../misc/md/course.json', 'r') as json_file:
            courses = json.load(json_file)
        return courses

    def create_courses(self):
        courses = self._read_courses()
        for course_json in courses['course']:
            course = Course.objects.create(
                title=course_json['title'], slug=course_json['slug'],
                overview='', semester=course_json['semester'],
                classroom=course_json['classroom'],
                course_teach_url=course_json['course_teach_url'],
                course_zone=course_json['course_zone'])

            for idx, lect in enumerate(course_json['lecture']):
                title = str(course) + ' lecture ' + str(idx + 1)
                lecture = Lecture.objects.create(
                    title=title, course=course,
                    start=str_to_dt(lect['start']), end=str_to_dt(lect['end']),
                )
                filepath = '../misc/md/{}/{}{}.txt'.format(
                    course_json['path_lecture'],
                    course_json['lecture_prefix'], str(idx + 1))
                with open(filepath, 'r') as f:
                    lecture.notes = f.read()
                lecture.save()

            for exam_json in course_json['exam']:
                title = str(course) + ' ' + exam_json['title']
                exam = Exam.objects.create(
                    title=title,
                    course=course,
                    start=str_to_dt(exam_json['start']),
                    end=str_to_dt(exam_json['end']),
                    started=exam_json['started'],
                    started_time=str_to_dt(exam_json['start'])
                )
                exam.save()
                for problem_json in exam_json['problem']:
                    problem_path = '/problem' + \
                        problem_json['problem_i'] + '.txt'
                    filepath = ('../misc/md/' +
                                exam_json['path_exam'] + problem_path)
                    with open(filepath, 'r') as f:
                        problem = Problem.objects.create(
                            content=f.read(),
                            minutes=problem_json['minutes'],
                            exam=exam,
                            full_marks=problem_json['full_marks']
                        )
                        problem.save()
                exam.update_problems()

    def teacher_comment(self, user_teach, user_student, text):
        resumes = user_student.resumes.all()
        for resume in resumes:
            for comment_i in range(3):
                comment = ResumeComment.objects.create(
                    resume=resume, commenter=user_teach, text=text[comment_i],
                    created_date=timezone.now() +
                    datetime.timedelta(hours=comment_i), )
                comment.save()

    def add_groups(self):
        content_type = ContentType.objects.get_for_model(User)
        for group in SITE_GROUPS:
            permission = Permission.objects.create(
                codename='is_' + group.lower(),
                name='Is a member of ' + group,
                content_type=content_type
            )
            new_group, created = Group.objects.get_or_create(name=group)
            new_group.permissions.add(permission)
            if group == GROUP_SUPERVISOR:
                perm = Permission.objects.get(codename__contains='add_user')
                new_group.permissions.add(perm)
                perm = Permission.objects.get(codename__contains='change_user')
                new_group.permissions.add(perm)
                perm = Permission.objects.get(codename__contains='add_course')
                new_group.permissions.add(perm)
                perm = Permission.objects.get(
                    codename__contains='change_course')
                new_group.permissions.add(perm)

    def insert_exam_dummy(self, exam, student, teacher, total_score=False):
        exam_paper, created = ExamPaper.objects.get_or_create(
            exam=exam,
            student=student,
        )
        if total_score:
            exam_paper.total_score = 60
            exam_paper.save()

        with open('../misc/md/answer1.txt', 'r') as f:
            codes = f.read()
            answer = Answer.objects.create(
                content=codes,
                problem=exam.problems.all()[0],
                exam_paper=exam_paper,
                amendment=codes,
            )
            answer.save()

            comment = InlineComment.objects.create(
                answer=answer,
                linenum=5,
                content='too complicated! try bubble sort',
                commenter=teacher,
            )
            comment.save()

            comment = InlineComment.objects.create(
                answer=answer,
                linenum=5,
                content='understood',
                commenter=student,
            )
            comment.save()

            comment = InlineComment.objects.create(
                answer=answer,
                linenum=15,
                content='excellent solution',
                commenter=teacher,
            )
            comment.save()

        with open('../misc/md/answer2.txt', 'r') as f:
            codes = f.read()
            answer = Answer.objects.create(
                content=codes,
                problem=exam.problems.all()[1],
                exam_paper=exam_paper,
                amendment=codes,
            )
            answer.save()

            comment = InlineComment.objects.create(
                answer=answer,
                linenum=8,
                content='comment on problem#2',
                commenter=teacher,
            )
            comment.save()

            comment = InlineComment.objects.create(
                answer=answer,
                linenum=8,
                content='comment on problem#2 amendment',
                commenter=teacher,
                is_amendment=True,
            )
            comment.save()

        return exam_paper

    def insert_interview_dummy(self, interviewee, interviewer, title):
        iv = Interview.objects.create(
            interviewee=interviewee,
            interviewer=interviewer,
            title=title,
        )
        iv.save()
        return iv

    def insert_task(self, assignor, assignee, status, ttype, target):
        task = Task.objects.create(
            assignor=assignor,
            assignee=assignee,
            status=status,
            ttype=ttype
        )
        if ttype == Task.RESUME:
            task.resume = target
        elif ttype == Task.INTERVIEW:
            task.interview = target
        elif ttype == Task.EXAM_PAPER:
            task.exam_paper = target
        task.save()

    def insert_task_dummy(self):
        ast = User.objects.get(username='ast')
        tea = User.objects.get(username='qingquan wang')

        stu = User.objects.get(username__contains='xiaoqiang')
        resume = Resume.objects.filter(user=stu, desc='job1').first()
        self.insert_task(tea, tea, Task.TODO, Task.RESUME, resume)
        resume = Resume.objects.filter(user=stu, desc='job2').first()
        self.insert_task(tea, ast, Task.TODO, Task.RESUME, resume)

        stu = User.objects.get(username__contains='muhua')
        iv = self.insert_interview_dummy(stu, tea, '1st mock interview')
        self.insert_task(tea, tea, Task.TODO, Task.INTERVIEW, iv)
        iv = self.insert_interview_dummy(stu, tea, '2nd mock interview')
        self.insert_task(tea, ast, Task.TODO, Task.INTERVIEW, iv)

        exam = Course.objects.get(id=1).exams.all()[0]
        ep = self.insert_exam_dummy(exam, stu, tea)
        self.insert_task(tea, tea, Task.TODO, Task.EXAM_PAPER, ep)
        exam = Course.objects.get(id=1).exams.all()[1]
        ep = self.insert_exam_dummy(exam, stu, tea)
        self.insert_task(tea, ast, Task.TODO, Task.EXAM_PAPER, ep)

    def create_user_course_relationship(self):
        filename = '../misc/md/user_course.json'
        with open(filename) as json_file:
            data = json.load(json_file)
        for obj in data['teaching']:
            teacher = User.objects.get(username=obj['user'])
            course = Course.objects.get(id=obj['course_id'])
            self.teach_course(teacher, course)
        for obj in data['enrolling']:
            student = User.objects.get(username=obj['user'])
            course = Course.objects.get(id=obj['course_id'])
            self.enroll_course(student, course)

    def insert_student_info(self, user):
        work_exp = WorkExperience.objects.create(
            user=user, company='Xiaogu', position='Software Engineer',
            start=timezone.now().date(),
        )
        work_exp.save()
        study_exp = StudyExperience.objects.create(
            user=user, college='NEU', major='CS',
            degree=StudyExperience.BS,
            start=timezone.now().date(),
        )
        study_exp.save()

        f = open('../misc/md/resume/job1.pdf', 'rb')
        myfile = File(f)
        resume = Resume.objects.create(
            user=user, desc='job1',
            file=myfile
        )
        resume.save()
        f.closed
        f1 = open('../misc/md/resume/job2.pdf', 'rb')
        myfile1 = File(f1)
        resume1 = Resume.objects.create(
            user=user, desc='job2',
            file=myfile1
        )
        resume1.save()
        f1.closed
        f2 = open('../misc/md/resume/job3.pdf', 'rb')
        myfile2 = File(f2)
        resume2 = Resume.objects.create(
            user=user, desc='job3',
            file=myfile2
        )
        resume2.save()
        f2.closed

    def bulk_insert_student(self):
        filename = '../misc/md/dummy_student_template.json'
        course = Course.objects.get(id=2)
        tea = User.objects.get(username='qingquan wang')
        exam = course.exams.first()
        with open(filename) as json_file:
            template = json_file.read()
        for i in range(1, 31):
            string = template.replace('[idx]', str(i))
            obj = json.loads(string)
            stu = User.objects.create(**obj)
            stu.groups.add(Group.objects.get(name='Student'))
            self.enroll_course(stu, course)
            if i % 3 == 0:
                self.insert_exam_dummy(exam, stu, tea, total_score=True)
            elif i % 3 == 1:
                self.insert_exam_dummy(exam, stu, tea, total_score=False)

    def insert_users(self):
        filename = '../misc/md/users.json'
        with open(filename) as json_file:
            data = json.load(json_file)
        for obj in data:
            user_obj = obj['user']
            user = User.objects.create(**user_obj)
            user.set_password(obj['password'])
            user.save()
            for group in obj['groups']:
                user.groups.add(Group.objects.get(name=group))
            if 'Student' in obj['groups']:
                self.insert_student_info(user)

    def insert_resume_comments(self):
        filename = '../misc/md/resume_reviews.json'
        with open(filename) as json_file:
            data = json.load(json_file)
        for obj in data:
            commenter = User.objects.get(username=obj['commenter'])
            student = User.objects.get(username=obj['student'])
            self.teacher_comment(commenter, student, obj['text'])

    def handle(self, *args, **options):
        self.add_groups()

        # Add users
        self.insert_users()

        # course
        self.create_courses()

        # course user relationship
        self.create_user_course_relationship()

        # insert a whole class and exam data
        self.bulk_insert_student()

        # resume_comment
        self.insert_resume_comments()

        # insert 3 tasks
        self.insert_task_dummy()

        self.stdout.write(self.style.SUCCESS('finished'))
